#include <iostream>
#include<string>
#include <eccrypto.h>
#include <osrng.h>
#include <oids.h>
#include <hex.h>
#pragma comment( lib, "cryptlib.lib" )
using namespace std;
using namespace CryptoPP;
int main()
{
	AutoSeededRandomPool prng;
	ECDSA<ECP, SHA256>::PrivateKey privateKey;
	privateKey.Initialize(prng, ASN1::secp256r1());
	const Integer& keyValue = privateKey.GetPrivateExponent();
	cout << "The private key is " << hex <<keyValue << endl;
	ECDSA<ECP, SHA256>::Signer signer(privateKey);
	string message;
	cout << "Please enter the message to sign ";
	getline(cin, message);
	size_t siglen = signer.MaxSignatureLength();
	string signature(siglen, 0x00);
	siglen = signer.SignMessage(prng, (const byte*)&message[0], message.size(), (byte*)&signature[0]);
	signature.resize(siglen);
	ECDSA<ECP, SHA256>::PublicKey publicKey;
	privateKey.MakePublicKey(publicKey);
	const Integer& publicKeyValueX = publicKey.GetPublicElement().x;
	const Integer& publicKeyValueY = publicKey.GetPublicElement().y;
	cout << "The public key is " << hex << publicKeyValueX << publicKeyValueY << endl;
	string tempPublicKey;
	cout << "Please enter the public key: ";
	getline(cin, tempPublicKey);
	HexDecoder decoder;
	decoder.Put((byte*)&tempPublicKey[0], tempPublicKey.size());
	decoder.MessageEnd();
	ECP::Point q;
	size_t len = decoder.MaxRetrievable();
	q.identity = false;
	q.x.Decode(decoder, len / 2);
	q.y.Decode(decoder, len / 2);
	ECDSA<ECP, SHA256>::PublicKey publicKey1;
	publicKey1.Initialize(ASN1::secp256r1(), q);
	if (!(publicKey == publicKey1))
	{
		cout << "Fail to verify!\n";
		system("pause");
		return 0;
	}
	ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
	bool change = 0;
	cout << "Is to change the signature(0 is false while 1 is true) ";
	cin >> change;
	bool result = verifier.VerifyMessage((const byte*)&message[0], message.size(), (const byte*)&signature[change], signature.size());
	if (result)
		cout << "Success to verify!\n";
	else
		cout << "Fail to verify!\n";
	system("pause");
	return 0;
}